#include "shader.h"

namespace qbe::utils::TempRender {

Mesh2D::Mesh2D(){};
Mesh2D::Mesh2D(uint32_t size) {
  vertices = vsg::vec2Array::create(size);
  indices = vsg::uintArray::create(size);
  vertices->properties.dataVariance = vsg::DYNAMIC_DATA;
};

Mesh2D::Mesh2D(vsg::ref_ptr<vsg::vec2Array> _vertices) {
  vertices = _vertices;
  indices = vsg::uintArray::create(vertices->size());
  for (uint32_t i = 0; i < vertices->size(); i++) {
    indices->at(i) = i;
  }
  vertices->properties.dataVariance = vsg::DYNAMIC_DATA;
};

Mesh2D::Mesh2D(vsg::ref_ptr<vsg::vec2Array> _vertices, vsg::ref_ptr<vsg::uintArray> _indices) {
  vertices = _vertices;
  indices = _indices;
  vertices->properties.dataVariance = vsg::DYNAMIC_DATA;
};

Mesh2D::Mesh2D(qlib::Vec2dArray points, bool connect, bool triangle) {
  gen_from_points(points, connect);
  if (triangle) {
    gen_tri_indices(points);
    indices = vsg::uintArray::create(tri_indices.size());
    for (uint32_t i = 0; i < indices->size(); i++) {
      (*indices)[i] = tri_indices[i];
    }
  }
  vertices->properties.dataVariance = vsg::DYNAMIC_DATA;
};

void Mesh2D::gen_from_points(qlib::Vec2dArray points, bool connect) {
  uint32_t size = points.size();
  if (size < 2) {
    return;
  }

  vertices = vsg::vec2Array::create(size);
  for (uint32_t i = 0; i < size; i++) {
    (*vertices)[i] = vsg::vec2{float(points[i].x), float(points[i].y)};
  }

  if (connect) {
    indices = vsg::uintArray::create(size * 2);
  } else {
    indices = vsg::uintArray::create((size - 1) * 2);
  }

  for (uint32_t i = 0; i < size - 1; i++) {
    (*indices)[i * 2] = i;
    (*indices)[i * 2 + 1] = i + 1;
  }
  // 收尾相连
  if (connect) {
    (*indices)[(size - 1) * 2] = size - 1;
    (*indices)[(size - 1) * 2 + 1] = 0;
  }
}

void Mesh2D::gen_tri_indices(qlib::Vec2dArray points) {
  tri_indices = qlib::tools::tri_earcut(points);
}

void Mesh2D::update(vsg::ref_ptr<vsg::vec2Array> _vertices) {
  (*vertices) = (*_vertices);
  auto t_indices = vsg::uintArray::create(vertices->size());
  for (uint32_t i = 0; i < vertices->size(); i++) {
    t_indices->at(i) = i;
  }
  (*indices) = (*t_indices);
}

void Mesh2D::print() {
  SPDLOG_INFO("vertices :");
  std::cout << "vertices :" << std::endl;
  for (uint32_t i = 0; i < vertices->size(); i++) {
    auto v = vertices->at(i);
    SPDLOG_INFO("[x,y]: [{}, {}] ", v.x, v.y);
    std::cout << "[x,y]:" << v.x << "," << v.y << std::endl;
  }
  std::cout << "indices :" << std::endl;
  for (uint32_t i = 0; i < indices->size(); i++) {
    auto v = indices->at(i);
    SPDLOG_INFO("{}", v);
    std::cout << v << std::endl;
  }
}

void Mesh2D::dirty() {
  is_dirty = true;
}

void mesh_merge(const std::vector<Mesh2D>& in_meshs, Mesh2D& out_meshs) {
  int start_index = 0;
  int total_vert = 0;
  int total_index = 0;
  for (auto i : in_meshs) {
    total_vert += i.vertices->size();
    total_index += i.indices->size();
  }
  out_meshs.vertices = vsg::vec2Array::create(total_vert);
  out_meshs.indices = vsg::uintArray::create(total_index);
  int offset_vert = 0;
  int offset_index = 0;
  for (auto i : in_meshs) {
    for (int j = 0; j < i.vertices->size(); j++) {
      (*out_meshs.vertices)[offset_vert] = (*i.vertices)[j];
      offset_vert++;
    }

    for (int j = 0; j < i.indices->size(); j++) {
      (*out_meshs.indices)[offset_index] = (*i.indices)[j] + start_index;
      offset_index++;
    }

    start_index += i.vertices->size();
  }
}
LineMeshNode::LineMeshNode() {}
LineMeshNode::LineMeshNode(vsg::ref_ptr<vsg::Options> _options, qlib::Tag _tag, Mesh2D _mesh, LineShaderMaterial2D _material,
                           VkPrimitiveTopology _primitiveTopology)
    : options(_options), tag(_tag), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {
  addPipe();
  if (mesh.vertices->size() != 0)
    addCommands();
}
LineMeshNode::~LineMeshNode(){};

void LineMeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  uniform = vsg::Value<Line_Uniform>::create();
  uniform->value().color = material.uniform.color;
  uniform->value().isDash = material.uniform.isDash;
  uniform->value().canvas = material.uniform.canvas;
  uniform->value().dash = material.uniform.dash;
  uniform->value().gap = material.uniform.gap;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void LineMeshNode::clear() {
  this->children.clear();
}

void LineMeshNode::addCommands() {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mesh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mesh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mesh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void LineMeshNode::update() {
  this->children.clear();
  addCommands();
}

void LineMeshNode::updateLayerType() {
  if (m_layer_type_func == nullptr)
    return;
  std::vector<std::string> param = m_layer_type_func(tag.layer);
  LayerParam layer_type;
  getLayerParam(param, layer_type);
  setLayerType(layer_type);
}

void LineMeshNode::setLayerType(LayerParam& param) {
  BorderParm border_parm = param.border_parm;
  if (border_parm.dash != 0 && border_parm.gap != 0) {
    uniform->value().isDash = true;
    uniform->value().dash = border_parm.dash;
    uniform->value().gap = border_parm.gap;
  } else {
    uniform->value().isDash = false;
  }
  uniform->value().color = param.border_color;
}

void LineMeshNode::setLayerType(vsg::vec4 color, std::string line_type) {
  LayerParam layer_param;
  if (line_type == "B99" || line_type == "") {
    layer_param.border_color = color;
    layer_param.border_parm = getLineType("B1");
  } else {
    layer_param.border_color = color;
    layer_param.border_parm = getLineType(line_type);
  }
  setLayerType(layer_param);
}

FillMeshNode::FillMeshNode(){};

FillMeshNode::FillMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, FillShaderMaterial2D _material, VkPrimitiveTopology _primitiveTopology)
    : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {
  addPipe();
  if (mesh.vertices->size() != 0)
    addCommands();
}
FillMeshNode::~FillMeshNode(){};

void FillMeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  /*auto color_blend = vsg::ColorBlendState::create();
  color_blend->logicOpEnable = true;
  color_blend->logicOp = VK_LOGIC_OP_OR;*/
  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  auto uniform = vsg::Value<Fill_Uniform>::create();
  uniform->value().color = material.uniform.color;
  uniform->value().width = material.uniform.width;
  uniform->value().space = material.uniform.space;
  uniform->value().line_width = material.uniform.line_width;
  uniform->value().dot = material.uniform.dot;
  uniform->value().angle = material.uniform.angle;
  uniform->value().scale = material.uniform.scale;
  uniform->value().only_side = material.uniform.only_side;
  uniform->value().use_point_grid = material.uniform.use_point_grid;
  uniform->value().useTexture = material.uniform.useTexture;
  uniform->value().use_overlapping_discoloration = material.uniform.use_overlapping_discoloration;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void FillMeshNode::clear() {
  this->children.clear();
}

void FillMeshNode::addCommands() {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mesh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mesh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mesh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void FillMeshNode::addMesh(const Mesh2D& mh) {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void FillMeshNode::update() {
  this->children.clear();
  addCommands();
}

void FillMeshNode::addCmd(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void FillMeshNode::addMeshs(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void FillMeshNode::updateMesh(const Mesh2D& mh) {
  this->children.clear();
  addMesh(mh);
}

void FillMeshNode::updateMeshs(const std::vector<Mesh2D>& meshs) {
  this->children.clear();
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

PointMeshNode::PointMeshNode(){};

PointMeshNode::PointMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, PointShaderMaterial2D _material,
                             VkPrimitiveTopology _primitiveTopology)
    : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {
  addPipe();
  if (mesh.vertices->size() != 0)
    addCommands();
}
PointMeshNode::~PointMeshNode(){};

void PointMeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  uniform = vsg::Value<Point_Uniform>::create();
  uniform->value().point_type = material.uniform.point_type;
  uniform->value().color = material.uniform.color;
  uniform->value().point_size = material.uniform.point_size;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void PointMeshNode::clear() {
  this->children.clear();
}

void PointMeshNode::addCommands() {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mesh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mesh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mesh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void PointMeshNode::addMesh(const Mesh2D& mh) {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void PointMeshNode::update() {
  this->children.clear();
  addCommands();
}

void PointMeshNode::addCmd(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void PointMeshNode::addMeshs(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void PointMeshNode::updateMesh(const Mesh2D& mh) {
  this->children.clear();
  addMesh(mh);
}

void PointMeshNode::updateMeshs(const std::vector<Mesh2D>& meshs) {
  this->children.clear();
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void PointMeshNode::setLayerType(vsg::vec4 color, int point_type, float point_size) {
  uniform->value().point_type = point_type;
  uniform->value().color = color;
  uniform->value().point_size = point_size;
}

GridNode::GridNode(vsg::ref_ptr<vsg::Options> _options, GridShaderMaterial2D _material) : options(_options), material(_material) {
  addPipe();
  addCommands();
}

GridNode::~GridNode() {}

double axisLoopOffset(double v, double step) {
  long long _v = v * 100000;
  long long _step = step * 100000;
  long long loopWidth = 1000000 * step;  // 坐标系以10 * 刻度尺最小单位的屏幕像素宽度无限循环

  if (abs(_v) > loopWidth) {
    _v = _v % long long(loopWidth);
  }
  return (_v + loopWidth) / 100000.0;
  // double loopWidth = 10 * step;
  // double _v = v;
  // if (abs(v) > loopWidth)
  //   _v = fmod(v, step);
  // return _v + loopWidth;
};
void GridNode::setGridParam(double w, double h, vsg::dvec2 tran, double step, vsg::vec4 bg_color, vsg::vec4 grid_color, bool show_grid,
                            bool show_point) {
  if (step < 1e-5)
    step = 0.001;
  uniform->value().transform_p = vsg::vec2(tran[0], tran[1]);
  uniform->value().loop_p = vsg::vec2(axisLoopOffset(tran[0], step), axisLoopOffset(tran[1], step));
  uniform->value().bg_color = bg_color;
  uniform->value().axis_color = grid_color;
  uniform->value().line_color = grid_color;
  uniform->value().width = float(w);
  uniform->value().height = float(h);
  uniform->value().step_v = float(step);
  uniform->value().device_ratio = 1.0;
  uniform->value().show_grid = show_grid ? 1 : 0;
  uniform->value().show_point = show_point ? 1 : 0;

  uniform->dirty();
}

void GridNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  uniform = vsg::Value<Grid_Uniform>::create();
  uniform->value().transform_p = material.uniform.transform_p;
  uniform->value().loop_p = material.uniform.loop_p;
  uniform->value().bg_color = material.uniform.bg_color;
  uniform->value().axis_color = material.uniform.axis_color;
  uniform->value().line_color = material.uniform.line_color;
  uniform->value().width = material.uniform.width;
  uniform->value().height = material.uniform.height;
  uniform->value().step_v = material.uniform.step_v;
  uniform->value().device_ratio = material.uniform.device_ratio;
  uniform->value().show_grid = material.uniform.show_grid;
  uniform->value().show_point = material.uniform.show_point;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
}

void GridNode::addCommands() {
  // 构建顶点数据
  auto vertices = vsg::vec2Array::create(
      {{width * 2000, -height * 2000}, {width * 2000, height * 2000}, {-width * 2000, height * 2000}, {-width * 2000, -height * 2000}});
  // 设置数据为动态可更新
  vertices->properties.dataVariance = vsg::DYNAMIC_DATA_TRANSFER_AFTER_RECORD;
  auto indexes = vsg::uintArray::create({0, 1, 2, 2, 3, 0});
  indexes->properties.dataVariance = vsg::DYNAMIC_DATA_TRANSFER_AFTER_RECORD;
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(indexes));
  drawCommands->addChild(vsg::DrawIndexed::create(indexes->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

}  // namespace qbe::utils::TempRender